﻿/*
ChangeTracking (a library for POCO change tracking).

Copyright (C) 2014 Dmitry Merzagitovich Arslanov

This library is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free
Software Foundation; either version 2.1 of the License, or (at your option) any
later version.

This library is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*/

using Microsoft.Win32;
using System.ComponentModel;
using System.Windows;
using System.Windows.Input;

namespace ChangeTrackingSample
{
    public sealed partial class MainWindow : Window
    {
        public Document Document
        {
            get { return (Document)GetValue(DocumentProperty); }
            set { SetValue(DocumentProperty, value); }
        }

        public static readonly DependencyProperty DocumentProperty =
            DependencyProperty.Register("Document",
                                        typeof(Document),
                                        typeof(MainWindow),
                                        new PropertyMetadata(null));

        public MainWindow()
        {
            InitializeComponent();
        }

        private bool SaveAs()
        {
            SaveFileDialog sfd = new SaveFileDialog()
            {
                Title = "Save as",
                Filter = "XAML (*.xaml)|*.xaml"
            };
            if (!sfd.ShowDialog().Value) return false;
            Document.FileName = sfd.FileName;
            return true;
        }

        private bool Save()
        {
            if (string.IsNullOrEmpty(Document.FileName))
            {
                if (!SaveAs()) return false;
            }
            Document.Save(Document.FileName);
            return true;
        }

        private bool CanClose()
        {
            if (Document != null)
            {
                if (Document.Tracker.Changed)
                {
                    switch (MessageBox.Show(
                                "Document has changes. Save?",
                                "Warning",
                                MessageBoxButton.YesNoCancel,
                                MessageBoxImage.Question))
                    {
                        case MessageBoxResult.Cancel:
                            return false;
                        case MessageBoxResult.Yes:
                            return Save();
                    }
                }
            }
            return true;
        }

        private void CanNew(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void New(object sender, ExecutedRoutedEventArgs e)
        {
            if (!CanClose()) return;
            Document = new Document();
        }

        private void CanOpen(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void Open(object sender, ExecutedRoutedEventArgs e)
        {
            if (!CanClose()) return;
            OpenFileDialog ofd = new OpenFileDialog()
            {
                Title = "Open",
                Filter = "XAML (*.xaml)|*.xaml"
            };
            if (!ofd.ShowDialog().Value) return;
            Document = Document.Load(ofd.FileName);
        }

        private void CanSave(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = Document != null ? Document.Tracker.Changed : false;
        }

        private void Save(object sender, ExecutedRoutedEventArgs e)
        {
            Save();
        }

        private void CanSaveAs(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = Document != null;
        }

        private void SaveAs(object sender, ExecutedRoutedEventArgs e)
        {
            if (SaveAs()) Document.Save(Document.FileName);
        }

        private void CanClose(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void Close(object sender, ExecutedRoutedEventArgs e)
        {
            Close();
        }

        private void CanAdd(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = Document != null;
        }

        private void Add(object sender, ExecutedRoutedEventArgs e)
        {
            using (ChangeTracking.Transaction transaction =
                    Document.Tracker.StartTransaction())
            {
                Document doc = Document;
                Document = null;
                doc.Database.Entities.Add(new Entity());
                doc.Tracker.Changed = true;
                Document = doc;
                transaction.Commit("Add entity");
            }
        }

        private void CanRemove(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = DataGrid != null ?
                           DataGrid.SelectedItem != null :
                           false;
        }

        private void Remove(object sender, ExecutedRoutedEventArgs e)
        {
            using (ChangeTracking.Transaction transaction =
                    Document.Tracker.StartTransaction())
            {
                Entity entity = DataGrid.SelectedItem as Entity;
                Document doc = Document;
                Document = null;
                doc.Database.Entities.Remove(entity);
                doc.Tracker.Changed = true;
                Document = doc;
                transaction.Commit("Remove entity");
            }
        }

        private void CanModify(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = DataGrid != null ?
                           DataGrid.SelectedItem != null :
                           false;
        }

        private void Modify(object sender, ExecutedRoutedEventArgs e)
        {
            using (ChangeTracking.Transaction transaction =
                    Document.Tracker.StartTransaction())
            {
                Entity entity = DataGrid.SelectedItem as Entity;
                Document doc = Document;
                Document = null;
                ModifyDialog dlg = new ModifyDialog()
                {
                    EntityName = entity.Name,
                    EntityValue = entity.Value
                };
                if (!dlg.ShowDialog().Value) return;
                entity.Name = dlg.EntityName;
                entity.Value = dlg.EntityValue;
                doc.Tracker.Changed = true;
                Document = doc;
                transaction.Commit(string.Format("Edit {0}", entity.Name));
            }
        }

        private void WndClosing(object sender, CancelEventArgs e)
        {
            e.Cancel = !CanClose();
        }

        private void CanRedo(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = Document != null ? Document.Tracker.CanRedo : false;
        }

        private void Redo(object sender, ExecutedRoutedEventArgs e)
        {
            Document doc = Document;
            Document = null;
            doc.Tracker.Redo();
            Document = doc;
        }

        private void CanUndo(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = Document != null ? Document.Tracker.CanUndo : false;
        }

        private void Undo(object sender, ExecutedRoutedEventArgs e)
        {
            Document doc = Document;
            Document = null;
            doc.Tracker.Undo();
            Document = doc;
        }
    }
}